import React from 'react';
import { is } from 'immutable';
import { connect } from 'react-redux';
import { findDOMNode } from 'react-dom';
import * as css from './style';
import * as action from '../../../redux/action';
import { fetch, store, handleError, inspect, merge } from '../../../utils/utils';


class UserPanel extends React.Component {

    shouldComponentUpdate(nextProps) {
        /**
         * 在这里对属性操作是因为控制面板展开的字段在unrender里
         *  需要在每次触发到数据更新时（即使render内数据未变）也更新data-show
         */
        let isShow = nextProps.USER.getIn(['unrender', 'isSpread']);
        findDOMNode(this).setAttribute('data-show', isShow);

        return !is(nextProps.USER.get('render'), this.props.USER.get('render'));
    }

    render() {
        let user = this.props.USER.toJS();
        let isshow = user.unrender.isSpread;

        return (
            <div className={ css.panel } data-show={ isshow } >
                {
                    user.unrender.isLogin
                        ? <div>
                            <UserBooks { ...user }
                                userLogout={ this.props.userLogout }
                                renewBook={ this.props.renewBook }
                                sendMessage={ this.props.sendMessage }
                                removeFeedBook={ this.props.removeFeedBook }/>
                        </div>
                        : <UserLogin { ...user }
                            userLogin={ this.props.userLogin }
                            sendMessage={ this.props.sendMessage }
                            mvUserpanel={ this.props.spreadUserPanel }/>
                }
                <div className={ css.siteinfo }>
                    畅校园图书查询
                    © { new Date().getFullYear() } CreatShare
                </div>
            </div>
        )
    }
}


/**
 *  user login block
 *  @props ... , state.user
 *  @props userLogin, redux action
 *  @props sendMessage, redux action
 *  @props mvUserpanel, redux action
 */
class UserLogin extends React.Component {

    constructor(props) {
        super(props);
        this.click = this.click.bind(this);
        this.visible = this.visible.bind(this);
        this.switchHide = this.switchHide.bind(this);
    }

    componentDidMount() {
        // 如果用户的动作是要绑定，即使localstorage中有数据也不会自动登录
        if (this.props.unrender.isGoBind === true) {
            return false;
        }
        // 本地存储过账号密码就自动登录
        let [u, p] = store.getItem('u', 'p');
        u && p && this.login(u, p, 0);
    }

    // 控制password是否可见
    visible(e) {
        e.preventDefault();
        let p = this.refs.p;
        p.type = p.type === 'text' ? 'password' : 'text';
    }

    // 用户登录, type为登陆类型, 0为自动登录
    login(username, password, type) {
        // check user input data
        let [uCK, pCK] = inspect(username, password);

        if (uCK.err === true || pCK.err === true) {
            // 自动登录的数据出现问题，则直接清除数据，不显示消息
            if (type === 0) {
                store.clear();
            } else {
                this.props.sendMessage(`${uCK.msg} ${pCK.msg}`);
            }
            return false;
        }

        // 当isGoBind为true时，请求增加OpenID字段用于绑定账户
        let isGoBind = this.props.unrender.isGoBind;

        fetch({
            do: 'user',
            username: username,
            password: password,
            OpenID: isGoBind === true ? this.props.unrender.WXID : undefined
        }).done(res => {
            if (res.error === true) {
                // 自动登录的数据出现问题，则直接清除数据，不显示消息
                if (type === 0) {
                    store.clear();
                    return false;
                }
                this.props.sendMessage(res.msg);
                return false;
            }

            // 有绑定反馈时向用户显示
            if (res.bindRes) {
                this.props.sendMessage(res.bindRes);
            }

            // 当前请求不是绑定且用户勾选自动登录时本地存储用户名密码
            if (isGoBind !== true && this.refs.r.checked) {
                store.setItem('u', username, 'p', password);
            }

            // 将当前用户输入的用户名merge金redux内，用于在userpanel顶部显示
            this.props.userLogin(merge(res, { user: username }));
        }).fail(handleError.bind(this));
    }

    // call login
    click(e) {
        e.preventDefault();
        // 因为iOS下中文大写有bug，所以在输入时用css显示大写，在这里自动转换大写
        this.login(this.refs.u.value.toUpperCase(), this.refs.p.value);
    }

    // 切换userpanel显示／隐藏
    switchHide(e) {
        e.preventDefault();
        this.props.mvUserpanel();
    }

    render() {
        let isGoBind = this.props.unrender.isGoBind;

        // replace 用于在绑定／登录两种操作中更换不同的用户提示
        let replace = {
            text: isGoBind === true ? '绑定' : '登录',
            isRememberMe: isGoBind === true ? undefined :
                <div>
                    <input type="checkbox" ref="r" id="rm"
                        defaultChecked="checked" />
                    <label htmlFor="rm">记住我</label>
                </div>
        };

        return (
            <div>
                <h3>{ replace.text } 畅校园·图书查询
                    <i className={ css.iconleft }
                        onClick={this.switchHide }
                        onTouchStart={this.switchHide }/>
                </h3>

                <div className={ css.login } >
                    <input type="text" maxLength="9" ref="u"
                        placeholder="图书证号. 例如：S03129999" />

                    <input type="password"
                        placeholder="密码，初始密码为123456" ref="p" />

                    <i className={ css.iconeye }
                        onClick={ this.visible }
                        onTouchStart={ this.visible }/>

                    { replace.isRememberMe }

                    <input type="button" value={ replace.text }
                        onClick={ this.click }
                        onTouchStart={ this.click }/>
                </div>
            </div>
        )
    }
}


/**
 *  user books block, include logout, borrow and feed.
 *  @props ... , state.user
 *  @props userLogout, redux action
 *  @props renewBook, redux action
 *  @props sendMessage, redux action
 *  @props removeFeedBook, redux action
 */
class UserBooks extends React.Component {

    constructor(props) {
        super(props);
        this.logout = this.logout.bind(this);
    }

    logout(e) {
        e.preventDefault();
        this.props.userLogout();
    }

    render() {
        let { user, timestamp, book, subscibe } = this.props.render;

        book = book.map(e => {
            e.timestamp = timestamp;
            return e;
        });

        return (
            <div>

                <div className={ css.usertitle }>
                    <span>{ user }</span>
                    <button className={ css.btn }
                        onClick={ this.logout }
                        onTouchStart={ this.logout }>退出</button>
                </div>

                <BookBorrow books={ book } renewBook={ this.props.renewBook }
                    sendMessage={ this.props.sendMessage }/>

                <BookFeed books={ subscibe } user={ user }
                    removeFeedBook={ this.props.removeFeedBook }/>
            </div>
        )
    }
}


/**
 *  book feed block.
 *  @props books: object, state.render.book
 *  @props renewBook, redux action
 *  @props sendMessage, redux action
 */
class BookFeed extends React.Component {

    constructor(props) {
        super(props);
        this.cancelLike = this.cancelLike.bind(this);
    }

    cancelLike(e) {
        e.preventDefault();

        let ctrlid = e.target.getAttribute('data-ctrlid')

        fetch({
            do: 'csub',
            ctrlid: ctrlid,
            username: this.props.user
        }).done(res => {
            if (res.error === false) {
                this.props.removeFeedBook(ctrlid);
            } else {
                this.props.sendMessage(res.msg);
            }
        }).fail(handleError.bind(this));
    }

    render() {
        let { books } = this.props;
        return (
            <div className={ css.bookblock }>
                <h4>已订阅</h4>
                {
                    books.map((e, i) =>
                        <div className={ css.bookfeed } key={ i }>
                            <p title={ e.title }>{ e.title.replace(/@#@/g, ' ') }</p>
                            <div>索书号：{ e.search_id } { e.shuku }</div>
                            <div>共 { e.allNum } 本，{ e.on } 本可借</div>
                            <i className={ css.iconfeed }
                                title="取消喜欢"
                                data-islike="true"
                                data-ctrlid={ e.ctrlid }
                                onClick={ this.cancelLike }
                                onTouchStart={ this.cancelLike }></i>
                        </div>
                    )
                }
                {
                    books.length === 0 ?
                        <div className={ css.nobook }>尚无订阅书籍</div> : undefined
                }
            </div>
        )
    }
}


/**
 *  book borrow block.
 *  @props books: object, state.render.subscibe
 *  @props user,state.render.user
 *  @props removeFeedBook, redux action
 */
class BookBorrow extends React.Component {
    render() {
        let books = this.props.books;
        return (
            <div className={ css.bookblock }>
                <h4>已借阅</h4>
                {
                    books.map((e, i) =>
                        <BookEach key={i} {...e} renewBook={this.props.renewBook}
                            sendMessage={this.props.sendMessage}/>
                    )
                }
                {
                    books.length === 0 ?
                        <div className={ css.nobook }>尚无借阅书籍</div> : undefined
                }
            </div>
        )
    }
}


/**
 *  each book in book feed or book borrow.
 *  @props ... , book in books
 *  @props renewBook, redux action
 *  @props sendMessage, redux action
 */
class BookEach extends React.Component {

    constructor(props) {
        super(props);
        this.renew = this.renew.bind(this);
    }

    // 续借
    renew(e) {
        e.preventDefault();
        let bookid = e.target.getAttribute('data-bookid');
        fetch({
            do: 'renew',
            ctrlid: bookid
        }).done(res => {
            if (res.result === true) {
                this.props.sendMessage('续借成功');
                this.props.renewBook(bookid, res.date, false);
            } else {
                this.props.sendMessage(res.msg);
            }
        }).fail(handleError.bind(this));
    }

    render() {
        let { title, time, timestamp, renew, bookid } = this.props;

        title = title.replace(/@#@/g, ' ');

        // 差的天数
        let diff = (Math.round(new Date(time).getTime() / 1000) - timestamp * 1) / 86400,
            text, type, rnBtn;

        // 剩余
        if (diff > 0) {
            text = '剩余';
            diff = Math.ceil(diff);
            type = diff > 3 ? css.green : css.yellow;
            // 超期
        } else {
            text = '超期';
            diff = Math.floor(-diff);
            type = css.red;
        }

        if (renew * 1 === 1) {
            rnBtn = <button className={ css.btn } data-bookid={ bookid }
                onClick={this.renew }
                onTouchStart={this.renew }>续借</button>;
        } else {
            rnBtn = <button className={ css.btn } disabled>不可续借</button>;
        }

        return (
            <div className={ css.bookeach }>
                <p title={ title }>{ title }</p>
                <div className={ type } title={`最后还书日期为 ${time}`}>{text} {diff} 天</div>
                { rnBtn }
            </div>
        )
    }
}

export default connect(state => ({ USER: state.USER }), action)(UserPanel);
